import React, { Component } from 'react';
import { Input, Modal, Form, message, Select } from 'antd';
import PropTypes from 'prop-types';
import _ from 'lodash';
import { addTarget, updateTarget } from '@api/task';
import validatorCreator from '@util/validator-creator';
import {
  IP_RE,
  IP_INTERVAL_RE,
  IPV4_CIDE_RE,
  IPV6_CIDE_RE,
  NAME_RE,
  URL_RE,
  IP_V6
} from '@util/constants';
import TagSelect from '@components/tag-select';
import OrgCascader from '@components/org-cascader';
import { getStaffList } from '@api/task';
import './index.less';

const FormItem = Form.Item;
const TextArea = Input.TextArea;
const prefixCls = 'target-manage-modal';

const formItemLayout = {
  labelCol: {
    span: 4
  },
  wrapperCol: {
    span: 20
  }
};

class IpManageModal extends Component {
  constructor(props) {
    super(props);
    this.state = {
      staffScreachList: [],
      staffPagination: {
        page: 1,
        pageSize: 10,
        count: 0
      }
    };
  }

  UNSAFE_componentWillReceiveProps(props) {
    const {
      detail = {},
      form: { setFieldsValue, resetFields },
      isAddIp = false
    } = props;
    if (this.props.detail !== props.detail) {
      const targets = _.get(detail, 'targets', []).join('\n');
      const name = _.get(detail, 'name', '');
      const tagIds = _.get(detail, 'tagOids', []);
      let staffId = '';
      if (detail.staff) {
        staffId = [detail.staff.nickname, detail.staff.email, detail.staff.telephone]
          .filter(Boolean)
          .join('/');
      }
      const organizationId = _.get(detail, 'organization.paths', [])
        .concat(_.get(detail, 'organizationOid'))
        .filter(Boolean);
      const newValue = { targets, name, tagIds, organizationId, staffId };
      setTimeout(() => {
        setFieldsValue(newValue);
      }, 100);
    }

    if (!this.props.modalVisible && isAddIp) {
      resetFields();
    }
    !this.props.modalVisible && this.state.staffScreachList.length === 0 && this.filterStaffList();
  }
  onSearch = e => {
    this.setState(
      {
        staffScreachList: [],
        staffPagination: { ...this.state.staffPagination, page: 1, search: e }
      },
      () => this.filterStaffList()
    );
  };
  scrollEnd = e => {
    const { staffPagination } = this.state;
    const { target } = e;
    e.persist();
    // 滚动 触底 看接口是否还有剩余的值没传过来
    if (target.scrollTop + target.offsetHeight + 1 >= target.scrollHeight) {
      const { page, pageSize, count } = staffPagination;
      if (page * pageSize < count) {
        this.setState({ staffPagination: { ...staffPagination, page: page + 1 } }, () =>
          this.filterStaffList()
        );
      }
    }
  };

  filterStaffList() {
    const { staffPagination, staffScreachList } = this.state;
    let query = {
      page: staffPagination.page,
      pageSize: staffPagination.pageSize,
      search: staffPagination.search
    };
    if (!query.search || query.search === 'undefined') {
      delete query.search;
    }
    getStaffList(query).then(res => {
      let list = staffScreachList.concat(_.get(res, 'data.data.list', []));
      this.setState({ staffScreachList: list });
      this.setState({
        staffPagination: { ...staffPagination, count: _.get(res, 'data.data.count', 0) }
      });
    });
  }
  targetValidate = (rule, value, callback) => {
    if (!value) {
      callback('IP或域名不能为空');
    }
    let targets = value.split(/[\n]/g);
    targets.map(item => {
      if (
        !(IP_RE.test(item) || IP_V6.test(item)) &&
        !IP_INTERVAL_RE.test(item) &&
        !IPV4_CIDE_RE.test(item) &&
        !IPV6_CIDE_RE.test(item) &&
        !URL_RE.test(item)
      ) {
        callback('请输入正确格式的IP或域名');
      }
      if (IPV6_CIDE_RE.test(item)) {
        const prefixLength = item.split('/')[1];
        if (prefixLength < 118) {
          callback('单个IPv6最大支持1024个地址');
        }
      }
    });
    let ipsError = '';
    for (let i = 0; i < targets.length; i++) {
      const target = targets[i];
      if (IP_INTERVAL_RE.test(target, true)) {
        const ipRange = target.split('-');
        const startIPArr = ipRange[0].split('.').map(Number);
        const endIPArr = ipRange[1].split('.').map(Number);
        if (startIPArr[0] !== endIPArr[0] || endIPArr[1] !== startIPArr[1]) {
          ipsError = '起始IP和末尾IP只允许最后两位不同';
          break;
        }
        const rangeC = endIPArr[2] - startIPArr[2];
        const rangeD = endIPArr[3] - startIPArr[3];
        const ipCount = rangeC * Math.pow(2, 8) + rangeD;
        if (ipCount <= 0) {
          ipsError = '起始IP必须小于末尾IP';
          break;
        }
      }
    }
    if (ipsError) {
      callback(ipsError);
    }
    callback();
  };

  addIpSuccess = () => {
    this.props.changeModalVisible(false, {});
    this.props.getTargetList();
  };

  clearStaff() {
    this.setState({
      staffScreachList: [],
      staffPagination: {
        page: 1,
        pageSize: 10,
        count: 0
      }
    });
  }

  onClickSubmit = () => {
    const {
      form: { validateFieldsAndScroll }
    } = this.props;
    validateFieldsAndScroll((err, values) => {
      if (err) {
        return;
      }
      const organizationIds = _.get(values, 'organizationId', []);
      let formattedData = {
        name: values.name.replace(/\s/g, ''),
        targets: values.targets.split(/[\n]/g).filter(i => i),
        staffId: _.get(values, 'staffId'),
        organizationId: organizationIds[organizationIds.length - 1],
        tagIds: _.get(values, 'tagIds', [])
      };

      formattedData = _.pickBy(formattedData, Boolean);
      // 20190626 添加失败却无报错bug
      // this.setState({ loading: true });

      let todo, successInfo, errorInfo, body;
      if (this.props.detail) {
        todo = updateTarget;
        successInfo = '修改成功';
        errorInfo = '修改失败';
        let staffId;
        let formStaffId = _.get(values, 'staffId', '');
        if (formStaffId && !formStaffId.split('').includes('/')) {
          staffId = formStaffId;
        } else if (formStaffId && formStaffId.split('').includes('/')) {
          let item = this.state.staffScreachList.find(
            r => [r.nickname, r.email, r.telephone].filter(Boolean).join('/') === formStaffId
          );
          item._id ? (staffId = item._id) : null;
        }
        formattedData.staffId = staffId;

        body = { ip_id: _.get(this.props.detail, '_id', '') };
      } else {
        todo = addTarget;
        successInfo = '添加成功';
        errorInfo = '添加失败';
        body = {};
      }
      // 20190626 修复添加失败却无报错bug，将57行代码移至下面。
      // 推测为react setState异步更新导致的bug，具体原因还未找出
      this.setState({ loading: true });
      if (!formattedData.staffId) {
        delete formattedData.staffId;
      }
      todo({ ...body, ...formattedData })
        .then(() => {
          message.success(successInfo);
          this.setState({ loading: false }, this.addIpSuccess);
        })
        .catch(err => {
          if (err && err.message) {
            message.error(err.message);
          } else {
            message.error(errorInfo);
          }
        });
      this.clearStaff();
    });
  };

  render() {
    const { staffScreachList, staffPagination } = this.state;
    const { modalVisible = false, detail = {} } = this.props;
    const {
      form: { getFieldDecorator, setFieldsValue }
    } = this.props;
    const targetArray = _.get(detail, 'targets', '');
    const targets = _.toString(targetArray).replace(/,/, '\n');
    const ipName = _.get(detail, 'name', '');

    return (
      <div className="password-modal">
        <Modal
          maskClosable={false}
          destroyOnClose={true}
          title={<span style={{ fontWeight: 600 }}>{detail._id ? '编辑' : '添加'}目标组</span>}
          className={`${prefixCls}-modal`}
          visible={modalVisible}
          width={520}
          ipManage
          onCancel={() => {
            this.clearStaff();
            this.props.changeModalVisible(false);
          }}
          onOk={this.onClickSubmit}
          okButtonProps={{ className: 'button-forwards' }}
        >
          <Form labelAlign="left" colon={false}>
            <FormItem {...formItemLayout} key="name" label="名称" required>
              {getFieldDecorator('name', {
                rules: [
                  {
                    validator: validatorCreator('名称', {
                      required: true
                    })
                  },
                  {
                    pattern: NAME_RE,
                    message: '您输入的格式有误，仅支持中文、英文、数字、特殊字符 - 、— \\ _ / ：~'
                  },
                  {
                    max: 32,
                    message: '您输入的内容超过32个字符限制'
                  }
                ],
                initialValue: detail && ipName
              })(<Input placeholder="请输入中文、英文、特殊字符或数字，不超过32个字符" />)}
            </FormItem>
            <FormItem {...formItemLayout} key="ip" label="目标组" required>
              {getFieldDecorator('targets', {
                rules: [{ validator: this.targetValidate }],
                initialValue: detail && targets
              })(
                <TextArea
                  rows={4}
                  placeholder={
                    '支持IPv4、IPv6、IPv4段、IPv6段、域名、URL，多个目标请用换行符分隔，如\n192.168.1.1\n2001:DB8:0:0:8:800:200C:417A\n192.168.1.1-192.168.255.25(最大到一个B段)\n11::11:00/118(最大支持1024个IPv6地址)\n192.168.1.0/24\nwww.example.com\nhttp://www.example.com'
                  }
                />
              )}
            </FormItem>
            <FormItem {...formItemLayout} key="organizationId" label="所属部门">
              {getFieldDecorator('organizationId', {
                initialValue: []
              })(<OrgCascader fetchBySelf={true} />)}
            </FormItem>
            <FormItem {...formItemLayout} key="staffId" label="管理员">
              {getFieldDecorator('staffId')(
                <Select
                  showSearch
                  placeholder="请输入管理员"
                  defaultActiveFirstOption={false}
                  allowClear
                  showArrow={false}
                  filterOption={false}
                  notFoundContent={null}
                  onSearch={this.onSearch}
                  onChange={e => {
                    if (!e) {
                      setFieldsValue({ staffId: '' });
                    }
                  }}
                  dropdownRender={menu => (
                    <>
                      <p style={{ padding: 10, marginBottom: -10, fontWeight: 800 }}>
                        所有用户({staffPagination.count})
                      </p>
                      {menu}
                    </>
                  )}
                  onPopupScroll={this.scrollEnd}
                >
                  {staffScreachList.map(staff => (
                    <Select.Option key={staff._id}>
                      {[staff.nickname, staff.email, staff.telephone].filter(Boolean).join('/')}
                    </Select.Option>
                  ))}
                </Select>
              )}
            </FormItem>
            <FormItem {...formItemLayout} key="tagIds" label="标签">
              {getFieldDecorator('tagIds', {
                valuePropName: 'selected',
                initialValue: []
              })(<TagSelect />)}
            </FormItem>
          </Form>
        </Modal>
      </div>
    );
  }
}

IpManageModal.propTypes = {
  form: PropTypes.object.isRequired,
  changeModalVisible: PropTypes.function,
  modalVisible: PropTypes.boolean,
  getTargetList: PropTypes.function,
  isAddIp: PropTypes.boolean,
  staffList: PropTypes.array,
  detail: PropTypes.object
};

export default Form.create()(IpManageModal);
